﻿#include "Buffer.h"

Buffer::Buffer(ImageClass& imageClass)
{
    m_Image.ImageHeight = imageClass.ImageHeight;
    m_Image.ImageWidth = imageClass.ImageWidth;
    m_Image.ImagePixel = imageClass.ImagePixel;
    m_BufferSize = m_Image.ImageHeight * m_Image.ImageWidth * m_Image.ImagePixel;		// 计算该图片占总字节数
    m_PBufferData = new BufferDataType[m_BufferSize];
    m_PBufferHead = m_PBufferData;
    m_PBufferTail = m_PBufferData;
    m_DataLen = 0;
    m_IsReceiveData = false;

}

bool Buffer::write(BufferDataType* data, size_t& dataLen, size_t rows)
{
    // std::cout << "进行一次write" << std::endl;
    if (data == nullptr) return false;
    if (dataLen == 0)	 return true;
    if (rows == 1)
    {
        // 如果是图片第一行数据应该初始化头、尾指针。重新开始缓存图片
        m_PBufferHead = m_PBufferData;
        m_PBufferTail = m_PBufferHead;
        m_DataLen = 0;
        m_IsReceiveData = true;
    }

    if (dataLen + m_DataLen > m_BufferSize)
    {
        // 此时越界(说明缓冲区中接收数据超出正常图片大小，数据异常)
        // 缓冲区进行一张图片的第一行数据
        m_IsReceiveData = false;
        return false;
    }
    if (m_IsReceiveData)
    {
        // 此时说明数据可以接收，且没有超出缓冲区大小
        memcpy(m_PBufferTail, data, dataLen);
        m_DataLen += dataLen;
        m_PBufferTail += dataLen;
    }
    if (m_DataLen >= m_BufferSize)
    {
        // 这里应该加上上锁逻辑
        // emit senderImageData(m_PBufferData, m_BufferSize);
        // 调用对应虚函数
        this->RecviceImage(m_DataLen);
        m_PBufferHead = m_PBufferData;
        m_PBufferTail = m_PBufferHead;
        m_DataLen = 0;
        m_IsReceiveData = false;
    }

    // std::cout << "收到数据,目前一层缓冲区保存数量: " << m_DataLen << " 标准容量: " << m_BufferSize <<std::endl;
    return true;
}

void Buffer::Read(BufferDataType* Rdata, size_t& dataLen)
{
    // 缓冲区中图像数据未存满不允许上层类获取
    if (Rdata == nullptr || m_BufferSize != m_DataLen)
    {
        dataLen = -1;
    }

    memcpy(Rdata, m_PBufferData, m_BufferSize);
    dataLen = m_BufferSize;
    m_PBufferHead = m_PBufferData;
    m_PBufferTail = m_PBufferHead;
    m_DataLen = 0;
    m_IsReceiveData = false;
}

void Buffer::SetImageClass(ImageClass& imageClass)
{
    m_Image = imageClass;
    // 因为该缓冲区大小与图片大小有关所以这里需要重新开辟空间，并将原本空间上的数据全部拷贝到新的堆上
    m_BufferSize = m_Image.ImageHeight * m_Image.ImagePixel * m_Image.ImageWidth;
    BufferDataType* tmp = new BufferDataType[m_BufferSize];
    memcpy(tmp, m_PBufferData, m_DataLen);
    delete m_PBufferData;

    m_PBufferData = tmp;
    m_PBufferHead = m_PBufferData;
    m_PBufferTail = m_PBufferHead + m_DataLen;
}

ImageBuffer::ImageBuffer(size_t imageBufferSize, ImageClass& imageClass)
    :m_ImageBufferSize(imageBufferSize), Buffer(imageClass)
{
    m_Image.ImageHeight = imageClass.ImageHeight;
    m_Image.ImageWidth = imageClass.ImageWidth;
    m_Image.ImagePixel = imageClass.ImagePixel;
    m_ImageSize = m_Image.ImageHeight * m_Image.ImageWidth * m_Image.ImagePixel;
    m_PImageV.resize(m_ImageBufferSize);

    BufferDataType* tmp;
    for (int i = 0; i < m_ImageBufferSize; ++i)
    {
        tmp = new BufferDataType[m_ImageSize];
        m_PImageV[i] = tmp;
    }

     m_ToImage = new DataToImageThread();
     m_ToImage->start();
}

ImageBuffer::~ImageBuffer()
{
    for (int i = 0; i < m_ImageBufferSize; ++i)
    {
        delete m_PImageV[i];
    }
}

bool ImageBuffer::readImage(BufferDataType** pImage)
{
    // if (pImage == nullptr) return false;
    if (m_ImageNumber == 0)
    {
        std::cout << "缓冲区中没有存有图片" << std::endl;
        return false;
    }

    *pImage = m_PImageV[m_ImageHead % m_ImageBufferSize];
    m_ImageHead = (++m_ImageHead) % m_ImageBufferSize;
    return true;
}

size_t ImageBuffer::GetImageLen()
{
    return m_ImageNumber;
}

void ImageBuffer::SetImageClass(ImageClass& imageClass)
{
    m_Image = imageClass;
    m_ImageSize = m_Image.ImageHeight * m_Image.ImageWidth * m_Image.ImagePixel;
}

void ImageBuffer::RecviceImage(int Datalen)
{
    // std::cout << "收到图片数据: " << &PBufferData << std::endl;
   // 进行传入数据长度判断，如果与规定大小不符合停止交换
    if (Datalen != m_ImageSize)
    {
        std::cout << "传入图片句柄有效长度与当前类规定长度异常";
        return;
    }
    std::swap(m_PImageV[(m_ImageHead + m_ImageNumber) % m_ImageBufferSize], m_PBufferData);		// 因为都是开辟在堆上的空间，所以直接交换两个指针即可。不需要进行不必要的拷贝
    if (m_ImageNumber == m_ImageBufferSize)
    { // 此时缓冲区中图片刚好达到容量。（不存在超过）即新插入
        m_ImageHead = (m_ImageHead + 1) % m_ImageBufferSize;									// 保证m_ImageHead数值合法
    }
    if (m_ImageNumber < m_ImageBufferSize) ++m_ImageNumber;
    // 缓冲区中存储图片数量变量值+1
    // std::cout << "存满一张图片进行保存" << std::endl;
    m_ToImage->setRead(m_PBufferData);
}

ImageClass::ImageClass(size_t imageWidth, size_t imageHeight, size_t imagePixel)
    :ImageHeight(imageHeight), ImageWidth(imageWidth), ImagePixel(imagePixel)
{
}
